using System;
using System.Collections.Generic;
using Godot;
using Godot.Collections;
using MyCraft2;

public partial class Block
{
    /*
     new ("",
        forwardTexturePath:"",
        backTexturePath:"",
        upTexturePath:"",
        downTexturePath:"",
        leftTexturePath:"",
        rightTexturePath:""),
     */
}

public partial class Block
{
    public static readonly Vector3[] Vertices =
    [
        new(-0.5f, -0.5f, -0.5f), // 前面左下角
        new(0.5f, -0.5f, -0.5f), // 前面右下角
        new(0.5f, 0.5f, -0.5f), // 前面右上角
        new(-0.5f, 0.5f, -0.5f), // 前面左上角

        new(0.5f, -0.5f, 0.5f), // 后面左下角
        new(-0.5f, -0.5f, 0.5f), // 后面右下角
        new(-0.5f, 0.5f, 0.5f), // 后面右上角
        new(0.5f, 0.5f, 0.5f) // 后面左上角
    ];

    public static readonly System.Collections.Generic.Dictionary<Vector3, int[]> FaceVerticesIndex = new()
    {
        { Vector3.Forward, [0, 1, 2, 0, 2, 3] },
        { Vector3.Back, [4, 5, 6, 4, 6, 7] },
        { Vector3.Up, [3, 2, 7, 3, 7, 6] },
        { Vector3.Down, [5, 4, 1, 5, 1, 0] },
        { Vector3.Left, [5, 0, 3, 5, 3, 6] },
        { Vector3.Right, [1, 4, 7, 1, 7, 2] }
    };

    internal static readonly List<Block> Instances = [];

    public static void Register(Block block)
    {
        Instances.Add(block);
        block.Id = Instances.Count - 1;
    }

    private static readonly List<Image> Images = [];
    internal static readonly Texture2DArray TextureArray = new();

    protected static int LoadTexture(string path)
    {
        var texture = ResourceLoader.Load<Texture2D>(path);
        var image = texture.GetImage();

        var existingIndex = Images.FindIndex(img => img.GetHashCode() == image.GetHashCode());
        if (existingIndex != -1)
            return existingIndex;

        Images.Add(image);
        return Images.Count - 1;
    }

    public static void BuildTextureArray()
    {
        var godotArray = new Array<Image>(Images);
        TextureArray.CreateFromImages(godotArray);
    }
}

public partial class Block
{
    public string Name { get; }
    public int Id { get; private set; }
    public BlockTexture ForwardTexture { get; }
    public BlockTexture BackTexture { get; }
    public BlockTexture UpTexture { get; }
    public BlockTexture DownTexture { get; }
    public BlockTexture LeftTexture { get; }
    public BlockTexture RightTexture { get; }
    public AudioStream PutAudioStream { get; }
    public AudioStream DestroyAudioStream { get; }

    public Block(string name,
        string forwardTexturePath, string backTexturePath,
        string upTexturePath, string downTexturePath,
        string leftTexturePath, string rightTexturePath,
        string putAudioStreamPath, string destroyAudioStreamPath,
        Color? forwardAlbedoColor = null, Color? backAlbedoColor = null,
        Color? updAlbedoColor = null, Color? downAlbedoColor = null,
        Color? leftAlbedoColor = null, Color? rightAlbedoColor = null)
    {
        Name = name;
        PutAudioStream = ResourceLoader.Load<AudioStream>(putAudioStreamPath);
        DestroyAudioStream = ResourceLoader.Load<AudioStream>(destroyAudioStreamPath);
        ForwardTexture = new BlockTexture { Id = LoadTexture(forwardTexturePath), AlbedoColor = forwardAlbedoColor };
        BackTexture = new BlockTexture { Id = LoadTexture(backTexturePath), AlbedoColor = backAlbedoColor };
        UpTexture = new BlockTexture { Id = LoadTexture(upTexturePath), AlbedoColor = updAlbedoColor };
        DownTexture = new BlockTexture { Id = LoadTexture(downTexturePath), AlbedoColor = downAlbedoColor };
        LeftTexture = new BlockTexture { Id = LoadTexture(leftTexturePath), AlbedoColor = leftAlbedoColor };
        RightTexture = new BlockTexture { Id = LoadTexture(rightTexturePath), AlbedoColor = rightAlbedoColor };
    }

    public BlockTexture GetTexture(Vector3 faceDirection)
    {
        if (faceDirection == Vector3.Forward)
            return ForwardTexture;
        if (faceDirection == Vector3.Back)
            return BackTexture;
        if (faceDirection == Vector3.Up)
            return UpTexture;
        if (faceDirection == Vector3.Down)
            return DownTexture;
        if (faceDirection == Vector3.Left)
            return LeftTexture;
        if (faceDirection == Vector3.Right)
            return RightTexture;
        throw new ArgumentException("Invalid direction");
    }
}